#pragma once
#include <set>
#include <vector>
#include <utility>
#include <map>
#include <cassert>

#include <cstdio>

struct ptr_list
{
	void *ptr;
	int cnt;

	ptr_list ()
	{
		next = 0;
		ptr = 0;
		cnt = 0;
	}

	ptr_list (void *v, int i)
	{
		next = 0;
		ptr = v;
		cnt = i;
	}


	ptr_list *next;
};

ptr_list *all_ptr = 0;


void add (ptr_list *&head, void *ptr, int cnt)
{
	ptr_list *nw = new ptr_list(ptr, cnt);
	nw->next = head;
	head = nw;
}

void clear (ptr_list *v)
{
	if (v->next != 0)
		clear(v->next);
	delete v;
}

void dec (void *p)
{
	if (p != 0)
		add(all_ptr, p, -1);
}

void inc (void *p)
{
	if (p != 0)
		add(all_ptr, p, 1);
}

ptr_list* collect ()
{
	std::map <void *, int> ptr_cnt;
	ptr_list* res = 0;

	for (ptr_list* i = all_ptr; i != 0; i = i->next)
	{
		if (ptr_cnt.count(i->ptr) == 0)
			ptr_cnt[i->ptr] = 0;
		ptr_cnt[i->ptr] += i->cnt;
	}

	for (std::map <void*, int>::iterator it = ptr_cnt.begin(); it != ptr_cnt.end(); it++)
	{
		assert(it->second >= 0);

		if (it->second > 0)
			add(res, it->first, it->second);
	}

	all_ptr = res;

	return res;
}
